package cmd

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/spf13/cobra"
)

var mysqlBackupDirectory, mysqlBackupLogDir string

// 备份文件检查子命令入口
var backupFileCheck = &cobra.Command{
	Use:   "mysqlbackupcheck",
	Short: "这是mysql全量备份文件检查工具",
	Args:  cobra.ArbitraryArgs, //接收任意参数
	Run: func(cmd *cobra.Command, args []string) {
		CheckBackup(mysqlBackupDirectory, mysqlPort)
	},
}

// checkBackup 检查备份文件和日志文件
func CheckBackup(backupDir string, port int) {
	yesterday := time.Now().AddDate(0, 0, -1)
	filename := fmt.Sprintf("full_%s.tar.gz", yesterday.Format("20060102"))
	filePath := filepath.Join(backupDir, filename)
	logFilePath := filepath.Join(mysqlBackupLogDir, fmt.Sprintf("full_backup_data_%s.log", yesterday.Format("2006-01-02")))

	// 检查备份文件是否存在
	if _, err := os.Stat(filePath); err == nil {
		//fmt.Printf("检测到备份文件: %s\n", filePath)

		if CheckLogFile(logFilePath) {
			//fmt.Printf("备份文件 %s 完整性检查通过。\n", filePath)
			status = 1 // 昨天的备份成功
		} else {
			fmt.Printf("备份文件 %s 的日志检查失败！\n", logFilePath)
		}
	} else if os.IsNotExist(err) {
		fmt.Printf("未找到备份文件: %s\n", filePath)
	} else {
		fmt.Printf("检查文件 %s 时发生错误: %v\n", filePath, err)
	}

	// 输出结果
	fmt.Printf("mysqlbackupcheck,port=%d status=%di\n", port, status)
}

// checkLogFile 检查日志文件的最后一行是否包含 "completed OK!"
func CheckLogFile(logFilePath string) bool {
	file, err := os.Open(logFilePath)
	if err != nil {
		fmt.Printf("打开日志文件 %s 时发生错误: %v\n", logFilePath, err)
		return false
	}
	defer file.Close()

	/*
		创建一个 bufio.Scanner 对象，用于逐行读取文件中的内容。
		for scanner.Scan() 循环会遍历文件的每一行，将当前行的内容存储到 lastLine 变量中。经过完整的循环后，lastLine 中将保存文件的最后一行文本
	*/
	var lastLine string
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		lastLine = scanner.Text()
	}
	//在读取完所有行后，使用 scanner.Err() 检查在扫描过程中是否发生错误。如果发生错误，则打印错误信息并返回 false
	if err := scanner.Err(); err != nil {
		fmt.Printf("读取日志文件 %s 时发生错误: %v\n", logFilePath, err)
		return false
	}
	//使用 strings.Contains() 函数检查 lastLine 是否包含字符串 "completed OK!"。
	return strings.Contains(lastLine, "completed OK!")
}
func init() {
	/*
		IntVarP 方法用于定义一个整数类型的命令行标志（flag）。
		第一个参数 &port 是一个指向变量的指针，它将接收命令行输入的值。
		第二个参数 "port" 是标志的名称，可以通过 --port 来指定。
		第三个参数 "p" 是短标志的名称，可以通过 -p 来指定。
		第四个参数 3306 是该标志的默认值。如果用户在运行程序时不指定 -p 或 --port 参数，则 port 变量将自动获取这个默认值。
		最后一个参数 "MySQL 端口" 是对该参数的描述。
		因此，在运行程序时，如果您不提供 -p 参数，port 将会默认设置为 3306。如果您希望使用不同的 MySQL 端口，您可以在命令行中指定该参数
	*/
	rootCmd.AddCommand(backupFileCheck)
	backupFileCheck.Flags().StringVarP(&mysqlBackupDirectory, "directory", "d", "/export/servers/data/mybackup/my3306/xtrabackup/data", "数据库备份存放目录")
	backupFileCheck.Flags().StringVarP(&mysqlBackupLogDir, "logDir", "L", "/export/servers/data/mybackup/my3306/xtrabackup/log", "数据库备份日志目录")
	backupFileCheck.Flags().IntVarP(&mysqlPort, "port", "P", 3306, "数据库端口")
}
